#pragma once
#include <iostream>
#include <vector>
#include "Mutex.hpp"
#include "Sem.hpp"

static int gcap=5;

template <typename T>
class RingQueue
{
    public:
    RingQueue(int cap=gcap)
    :_cap(cap),_ring_queue(cap),_p_step(0),_c_step(0),_space_sem(cap),_data_sem(0)
    {}
    void Pop(T *out)
    {
        _data_sem.P();
        {
            LockGuard lockguard(&_c_lock);
            *out = _ring_queue[_c_step++];
            _c_step%=_cap;
        }
        _space_sem.V();
    }
    void Enqueue(T & in)
    {
        _space_sem.P();
        {
            LockGuard lockguard(&_p_lock);
            _ring_queue[_p_step++]=in;
            _p_step%=_cap;
        }
        _data_sem.V();
    }
    ~RingQueue(){}

    private:
    std::vector<T> _ring_queue;// 临界资源
    int _cap;

    Mutex _c_lock;
    Mutex _p_lock;

    Sem _space_sem;
    Sem _data_sem;

     // 生产和消费的位置
    int _p_step;
    int _c_step;
}; 